#pragma once

#include <linux/segment.h>

#define sti() __asm__ __volatile__("sti" \
                                   : \
                                   : \
                                   : "memory")
#define cli() __asm__ __volatile__("cli" \
                                   : \
                                   : \
                                   : "memory")

#define save_flags(x) \
    __asm__ __volatile__("pushfl ; popl %0" \
                         : "=r"(x) \
                         : /* no input */ \
                         : "memory")

#define restore_flags(x) \
    __asm__ __volatile__("pushl %0 ; popfl" \
                         : /* no output */ \
                         : "r"(x) \
                         : "memory")

#define _set_gate(gate_addr, type, dpl, addr) \
    __asm__ __volatile__("movw %%dx,%%ax\n\t" \
                         "movw %2,%%dx\n\t" \
                         "movl %%eax,%0\n\t" \
                         "movl %%edx,%1" \
                         : "=m"(*((long *)(gate_addr))), \
                           "=m"(*(1 + (long *)(gate_addr))) \
                         : "i"((short)(0x8000 + (dpl << 13) + (type << 8))), \
                           "d"((char *)(addr)), "a"(KERNEL_CS << 16))

#define set_trap_gate(n, addr) \
    _set_gate(&idt[n], 15, 0, addr)

#define set_system_gate(n, addr) \
    _set_gate(&idt[n], 15, 3, addr)
